Obsidian のデイリーノートを一括置換するスクリプト
作成日
更新日
- Obsidian のディレクトリ構造を一括で変換するスクリプトと同様に行う。
import os
import shutil
import re
import uuid
# ルートディレクトリ
PUBLIC_DIR = os.path.join(os.getcwd(), "public")
# 出力先フォルダ
DAILY_NOTE_DIR = os.path.join(os.getcwd(), "100_DailyNote")
IMAGES_DIR = os.path.join(os.getcwd(), "002_Images")
# 必要なフォルダを作成
os.makedirs(DAILY_NOTE_DIR, exist_ok=True)
os.makedirs(IMAGES_DIR, exist_ok=True)
# `coverImage` のパスを取得し、見つからなければ適切に補正する
def get_cover_image_path(images_folder, cover_image):
if not cover_image or cover_image.strip() == "":
return None
cover_image_path = os.path.join(images_folder, cover_image)
# `coverImage` に拡張子がある場合は、そのままチェック
if os.path.exists(cover_image_path):
return cover_image_path
# 拡張子がない場合、`.png`, `.jpg`, `.jpeg` を試す
if "." not in cover_image:
for ext in [".png", ".jpg", ".jpeg"]:
temp_path = os.path.join(images_folder, cover_image + ext)
if os.path.exists(temp_path):
return temp_path
print(f"カバー画像が見つかりません: {cover_image}")
return None
# `coverImage` を移動し、メタデータを更新し、挿入用の Markdown を生成
def process_cover_image(cover_image, note_date, year):
images_folder = os.path.join(PUBLIC_DIR, str(year), "images")
cover_image_path = get_cover_image_path(images_folder, cover_image)
if cover_image_path is None:
return None, ""
# **ファイルごとに新しいUUIDを生成**
unique_id = uuid.uuid4().hex
ext = os.path.splitext(cover_image_path)[1] # `.png`, `.jpg`, `.jpeg` など
new_cover_image_name = f"{note_date}-{unique_id}{ext}"
dst_image_path = os.path.join(IMAGES_DIR, new_cover_image_name)
try:
shutil.move(cover_image_path, dst_image_path)
markdown_link = f"[](../002_Images/{new_cover_image_name})\n\n"
return new_cover_image_name, markdown_link
except Exception as e:
print(f"カバー画像移動エラー: {cover_image_path} → {dst_image_path} ({e})")
return None, ""
# **該当ノート内の画像のみを移動**
def move_referenced_images(source_folder, note_date, content):
image_map = {}
images_path = os.path.join(source_folder, "images")
if os.path.exists(images_path):
# **マークダウン内で参照されている画像のみを取得**
referenced_images = re.findall(r'!\[[^\]]*\]\(images/([^)\s]+)\)', content)
for image in referenced_images:
src_image_path = os.path.join(images_path, image)
if os.path.exists(src_image_path):
name, ext = os.path.splitext(image)
new_image_name = f"{note_date}-{uuid.uuid4().hex}{ext}"
dst_image_path = os.path.join(IMAGES_DIR, new_image_name)
try:
shutil.move(src_image_path, dst_image_path)
image_map[image] = new_image_name
except Exception as e:
print(f"画像移動エラー: {src_image_path} → {dst_image_path} ({e})")
# **画像フォルダが空になったら削除**
if os.path.exists(images_path) and not os.listdir(images_path):
shutil.rmtree(images_path)
return image_map
# デイリーノートを処理
def process_daily_notes(year):
notes_dir = os.path.join(PUBLIC_DIR, str(year))
if not os.path.exists(notes_dir):
return
for file in sorted(os.listdir(notes_dir)): # ファイルごとに正しく処理
file_path = os.path.join(notes_dir, file)
if file.endswith(".md"):
# **各ファイルの `note_date` を個別に取得**
note_date = os.path.splitext(file)[0] # `YYYY-MM-DD`
new_md_path = os.path.join(DAILY_NOTE_DIR, f"{note_date}.md")
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# `coverImage` の値を取得(ない場合は None にする)
cover_image_match = re.search(r'coverImage:\s*(\S+)', content)
cover_image = cover_image_match.group(1) if cover_image_match else None
# `coverImage` を処理(UUID付き新ファイル名へ変更)
cover_image_markdown = ""
if cover_image:
new_cover_image_name, cover_image_markdown = process_cover_image(cover_image, note_date, year)
if new_cover_image_name:
content = re.sub(r'coverImage:\s*\S+', f'coverImage: {new_cover_image_name}', content)
# **`coverImage` の画像をメタデータの直後に挿入**
if cover_image_markdown:
content = re.sub(r'^(---\n.*?---\n)', rf'\1\n{cover_image_markdown}', content, count=1, flags=re.DOTALL)
# **該当ノートで参照されている画像のみを移動**
image_map = move_referenced_images(notes_dir, note_date, content)
for old_name, new_name in image_map.items():
escaped_old_name = re.escape(old_name)
content = re.sub(
rf'!\[[^\]]*\]\(images/{escaped_old_name}\)',
rf'',
content
)
content = re.sub(
rf'\[!\[[^\]]*\]\(images/{escaped_old_name}\)\]\(images/[^)]*\)',
rf'[](../002_Images/{new_name})',
content
)
# **変更を `100_DailyNote` に保存**
with open(new_md_path, "w", encoding="utf-8") as f:
f.write(content)
# **元の `.md` を削除**
os.remove(file_path)
# **すべての年を処理**
for year in range(2024, 2030): # 必要に応じて範囲を調整
process_daily_notes(year)
print("デイリーノートの変換が完了しました。")

公開日
更新日